Paquetes necesarios

Definimos inicialmente todos los paquetes que vamos necesitar para el trabajo.

Code
rm(list = ls())
library(tidyverse)
library(lubridate)
library(dplyr)
library(stringr)
library(glue)
library(forcats)
library(ggplot2) 

Carga de las bases de datos

La práctica se basará en los archivos de datos electorales que se indican a continuación, recopilando datos sobre las elecciones al Congreso de los Diputados en España desde 2008 hasta la actualidad, así como encuestas, códigos de municipios y abreviaturas

Code
election_data <- read_csv(file = "./data/datos_elecciones_brutos.csv")
cod_mun <- read_csv(file = "./data/cod_mun.csv")
surveys <- read_csv(file = "./data/historical_surveys.csv")
abbrev <- read_csv(file = "./data/siglas.csv")

Bases de datos

El trabajo consta de 4 bases de datos:

  • election_data: archivo con las elecciones al congreso
  • cod_mun: archivo con los códigos y nombres de cada municipio
  • abbrev: siglas de cada partido
  • surveys: encuestas electorales desde 1982.

Datos

  • election_data: archivo con las elecciones al congreso
    • tipo_eleccion: tipo de elecion (nacional, regional…)
    • anno: Año de la eleccion
    • mes: Mes de la eleccion
    • vuelta
    • codigo_ccaa: Código de la comunidad autónoma
    • codigo_provincia:Código de la provincia
    • codigo_municipio: Código del municipio
    • codigo_distrito_electoral: Código del distrito
    • numero_mesas: Número de mesas disponibles

Datos

  • election_data: archivo con las elecciones al congreso
    • censo: Número de personas del municipio
    • participacion_1
    • participacion_2
    • votos_blancos: Cantidad de votos en blanco
    • votos_nulos: Cantidad de votos nulos
    • votos_candidaturas: Cantidad de votos validos

Datos

  • surveys: encuestas electorales desde 1982.
    • type_survey: tipo de encuesta (nacional, regional…)
    • date_elec: fecha de las futuras elecciones
    • id_pollster, pollster, media: id y nombre de la empresa encuestadora, así como medio que la encargó
    • field_date_from, field_date_to: fechas de inicio y fin del trabajo de la encuesta
    • exit_poll: ¿es una encuesta a pie de urna?
    • size: tamaño muestral de la encuesta
    • turnout: participación (estimación)

Objetivos

El objetivo de la entrega es realizar un análisis de los datos electorales, llevando a cabo la depuración, los resúmenes y los gráficos que consideres necesarios, tanto de los resultados como de la precisión de las encuestas electorales.

En concreto, debes trabajar únicamente en el período de tiempo que incluye las elecciones desde 2008 hasta las últimas elecciones de 2019

Limpieza de la base de datos

Paso 1: Transformación de los datos al formato tidy
Code
# Transforma los datos de surveys en tidydata 
surveys_tidy <- surveys |>  
  pivot_longer( cols = "UCD":"EV", 
                names_to = "partidos", 
                values_to = "prob_votos",
                values_drop_na = TRUE
  )

# Transforma los datos de election_data en tidydata 
election_data_tidy <- election_data |>  
  pivot_longer( cols = "BERDEAK-LOS VERDES":"COALICIÓN POR MELILLA", 
                names_to = "partidos", 
                values_to = "votos" ,
                values_drop_na = TRUE
  ) |> unite(c("codigo_ccaa","codigo_provincia", "codigo_municipio"),col="cod_mun",sep='-')
Paso 2: Unión de las bases de datos
Code
# Union de election_data_tidy con las siglas de los partidos y con los nombres de municipios
election_data_tidy <- election_data_tidy |> 
  left_join(abbrev, by = c("partidos" = "denominacion")) |> 
  left_join(cod_mun, by = c("cod_mun" = "cod_mun"))


# Union de surveys_tidy con las siglas de los partidos
surveys_tidy <- surveys_tidy |> 
  left_join(abbrev, by = c("partidos" = "siglas"))

surveys_tidy <- surveys_tidy |> 
  rename(siglas = partidos)      # Cambiar "partidos" a "siglas" 

surveys_tidy <- surveys_tidy |> 
  rename( partidos = denominacion)  # Cambiar "denominacion" a "partidos"

# Verificar las uniones
head(surveys_tidy)
head(election_data_tidy)
Paso 3: Reagrupación de los partidos de los datos
Code
# Reagrupa los partidos de los datos "surveys_tidy"

surveys_tidy <- surveys_tidy |> 
  mutate(partidos = case_when(
    str_detect(partidos,"SOCIALISTA") ~ "PSOE",
    str_detect(partidos,"PARTIDO POPULAR") ~ "PP",
    str_detect(partidos,"CIUDADANOS") ~ "CS",
    str_detect(partidos,"VASCO") ~ "PNV",
    str_detect(partidos,"BLOQUE NACIONALISTA GALEGO") ~ "BNG",
    str_detect(partidos,"PODEMOS") ~ "UP",
    str_detect(partidos,"ESQUERRA.*CATALUNYA|CATALUNYA.*ESQUERRA") ~ "ERC",
    str_detect(partidos,"BILDU") ~ "EH - BILDU",
    str_detect(partidos,"VOX") ~ "VOX",
    TRUE ~ "OTROS"
  ))
  
head(surveys_tidy)

# Reagrupa los partidos de los datos "election_data_tidy"
election_data_tidy <- election_data_tidy |> 
  mutate(partidos = case_when(
    str_detect(partidos,"SOCIALISTA") ~ "PSOE",
    str_detect(partidos,"PARTIDO POPULAR") ~ "PP",
    str_detect(partidos,"CIUDADANOS") ~ "CS",
    str_detect(partidos,"VASCO") ~ "PNV",
    str_detect(partidos,"BLOQUE NACIONALISTA GALEGO") ~ "BNG",
    str_detect(partidos,"PODEMOS") ~ "UP",
    str_detect(partidos,"ESQUERRA.*CATALUNYA|CATALUNYA.*ESQUERRA") ~ "ERC",
    str_detect(partidos,"BILDU") ~ "EH - BILDU",
    str_detect(partidos,"VOX") ~ "VOX",
    TRUE ~ "OTROS"
  ))
election_data_tidy

Limpieza de la base de datos

Paso 4: Filtro de datos

Se aplicaron filtros a la base de datos inicial para cumplir con el objetivo del trabajo:

Code
# Filtro aplicado en los datos de surveys_tidy
surveys_filtered <- surveys_tidy |>  
  mutate(date_elec = as.Date(date_elec, format = "%Y-%m-%d"), # paquete lubridate
    field_date_to = as.Date(field_date_to, format = "%Y-%m-%d"), 
    field_date_from = as.Date(field_date_from, format = "%Y-%m-%d"),
    ano_elec = year(date_elec), # paquete necesario lubridate
    tiempo_trabajo_campo = as.numeric(field_date_to-field_date_from)) |> 
  filter(2008 >= ano_elec & ano_elec <= 2019 
         & exit_poll == FALSE 
         & (size >= 500 | !is.na(size))
         & tiempo_trabajo_campo >= 1)

# Filtro aplicado en los datos de election_data_tidy
election_filtered <- election_data_tidy |>  
  filter(partidos %in% c('PSOE', 'PP', 'CS', 'PNV', 'BNG', 'UP', 'ERC', 'EH - BILDU', 'VOX' ))
Code
# Selecion previa de las variables 
election_data_tidy_select <- election_filtered |>
  select('anno', 'cod_mun', 'numero_mesas','censo', 'participacion_1', 'participacion_2', 'votos_blancos', 'votos_nulos','votos_candidaturas','partidos','votos')

surveys_tidy_select <- surveys_filtered |>
  select('size', 'turnout', 'partidos', 'prob_votos', 'ano_elec','tiempo_trabajo_campo', 'id_pollster', 'pollster', 'media') |> 
  rename('tamano_muestra' = 'size',
         'estimacion_participac' = 'turnout')

# Join
datos_election <- election_data_tidy_select |> 
  left_join(cod_mun, by = "cod_mun")

EJERCICIOS

Pregunta 1: ¿Qué partido fue el ganador en los municipios con más de 100.000 habitantes (censo) en cada una de las elecciones?

Code
tabla_ganadores <- election_filtered |> 
  filter(censo > 100000) |> 
  arrange(municipio, anno, mes, desc(votos)) |> 
  summarise(vencedor = first(partidos), .by = c(anno, mes, municipio)) 
Code
# Agrupación de ganadores por año
ganadores_por_anno <- tabla_ganadores |> 
  group_by(anno, vencedor) |> 
  summarise(count = n(), .groups = "drop")

# Identificar los 3 partidos predominantes por número total de municipios ganados
partidos_predominantes <- ganadores_por_anno |> 
  group_by(vencedor) |> 
  summarise(total_municipios = sum(count), .groups = "drop") |> 
  arrange(desc(total_municipios)) |> 
  slice_head(n = 3) |> 
  pull(vencedor)

# Agrupar los partidos no predominantes como "OTROS"
ganadores_agrupados <- ganadores_por_anno |> 
  mutate(vencedor = ifelse(vencedor %in% partidos_predominantes, vencedor, "OTROS")) |> 
  group_by(anno, vencedor) |> 
  summarise(count = sum(count), .groups = "drop") # Sumar los valores de "OTROS"

# Graficar con los partidos agrupados
ggplot(ganadores_agrupados, aes(x = anno, y = count, fill = vencedor)) +
  geom_bar(stat = "identity", position = "stack") +
   geom_text(
    aes(
      label = paste0(count),
      color = vencedor),
    position = position_stack(vjust = 0.5), # Centra las etiquetas en las barras
    size = 3, 
    color = "white"
  ) +
  scale_x_continuous(breaks = unique(ganadores_agrupados$anno),  # Etiquetas de años
                     labels = unique(ganadores_agrupados$anno)) +
  scale_fill_manual(
    values = c(
      "VOX" = "#80b042",      
      "PP" = "#004a95",
      "PSOE" = "#e30613",
      "UP" = "#a668f3",
      "CS" = "#ff956a",
      "PNV" = "#917b66",
      "ERC" = "#edc158",
      "OTROS" = "gray" 
    )
  ) +
  labs(
    title = "Distribución de Partidos Ganadores por Año",
    x = "Año",
    y = "Número de Municipios",
    fill = "Partido Ganador"
  ) +
  theme_minimal() +
  theme(
    panel.background = element_rect(fill = "transparent", color = NA),  # Fondo del panel transparente
    plot.background = element_rect(fill = "transparent", color = NA),   # Fondo general transparente
    legend.background = element_rect(fill = "transparent", color = NA)  # Fondo de la leyenda transparente
  )

Pregunta 2: ¿Qué partido fue el segundo cuando el primero fue el PSOE? ¿Y cuando el primero fue el PP?

Primero identificamos el partido ganador y el segundo partido genador en cada una de las elecciones

Code
# Función para identificar el segundo partido cuando el primero es el especificado
partido_vencedor1 <- function(partido_venc) {
  election_filtered |> 
    filter(censo > 100000) |>                # Filtrar por municipios con más de 100,000 habitantes
    group_by(anno,mes, municipio) |>             # Agrupar por año y municipio
    arrange(desc(votos)) |>                  # Ordenar por número de votos en orden descendente
    mutate(posicion = row_number()) |>       # Asignar posición (1 = primero, 2 = segundo)
    summarise(
      primero_partido = partidos[posicion == 1],  # Partido ganador
      segundo_partido = partidos[posicion == 2], # Partido en segundo lugar
      .groups = "drop"
    ) |> 
    filter(primero_partido == partido_venc)  # Filtrar para que el partido ganador sea el especificado
}
# Obtener resultados cuando el primero es PSOE
resultados_psoe <- partido_vencedor1("PSOE")
# Obtener resultados cuando el primero es PP
resultados_pp <- partido_vencedor1("PP")
# Mostrar los resultados
resultados_psoe
resultados_pp

Posteriormente sobre el mismo código eliminamos los municipios en los que el partido ganador y el segundo ganador es el mismo

Code
partido_vencedor <- function(partido_venc) {
  election_filtered |> 
    filter(censo > 100000) |>                 # Filtrar por municipios con más de 100,000 habitantes
    group_by(anno, mes, municipio) |>         # Agrupar por año, mes y municipio
    arrange(desc(votos)) |>                   # Ordenar por número de votos en orden descendente
    mutate(posicion = row_number()) |>        # Asignar posición (1 = primero, 2 = segundo, etc.)
    filter(
      (posicion == 1 & partidos == partido_venc) |  # Mantener el ganador que corresponde al filtro
      (posicion == 2 & partidos != partido_venc)    # Asegurar que el segundo partido sea diferente al ganador
    ) |> 
    reframe(
      primero_partido = partidos[posicion == 1],
      segundo_partido = partidos[posicion == 2],
      anno = unique(anno),      # Asegurar que el año se incluya
      mes = unique(mes),
      municipio = unique(municipio)
    )
}

# Obtener resultados cuando el primero es PSOE
resultados_psoe <- partido_vencedor("PSOE")

# Obtener resultados cuando el primero es PP
resultados_pp <- partido_vencedor("PP")

# Mostrar los resultados ajustados
resultados_psoe
resultados_pp

Pregunta 2: ¿Qué partido fue el segundo cuando el primero fue el PSOE? ¿Y cuando el primero fue el PP?

Code
library(ggplot2)

# Crear un dataset combinado para ambos casos (PSOE y PP)
resultados_psoe <- partido_vencedor("PSOE") |> mutate(ganador = "PSOE")
resultados_pp <- partido_vencedor("PP") |> mutate(ganador = "PP")
resultados_comb <- bind_rows(resultados_psoe, resultados_pp)

# Gráfico de barras apiladas
ggplot(resultados_comb, aes(x = ganador, fill = segundo_partido)) +
  geom_bar() +
  scale_fill_manual(
    values = c(
     "VOX" = "#80b042",      
      "PP" = "#004a95",
      "PSOE" = "#e30613",
      "UP" = "#a668f3",
      "CS" = "#ff956a",
      "PNV" = "#917b66",
      "ERC" = "#edc158",
      "OTROS" = "gray" 
    )
  ) +
  labs(
    title = "Distribución de Segundos Partidos por Partido Ganador",
    x = "Partido Ganador",
    y = "Número de Municipios",
    fill = "Segundo Partido"
  ) +
  theme_minimal()

Pregunta 3: ¿Cómo calibrar el error de las encuestas (recordemos que las encuestas son de intención de voto a nivel nacional)?

Code
# Función para calibrar el error y generar tablas de salida
calibrar_error <- function(election_data, surveys) {

  
  # Preparación de los datos de las elecciones: cálculo del porcentaje real de votos
  election_data_grouped <- election_data |>
    group_by(anno, partidos) |>
    summarise(
      actual_votes = sum(votos, na.rm = TRUE), # Total de votos por partido
      total_votes = sum(votos_candidaturas, na.rm = TRUE), # Total de votos válidos
      .groups = "drop"
    ) |>
    mutate(
      actual_share_percent = (actual_votes / total_votes) * 100 # Porcentaje real de votos
    )
  
  # Vincular encuestas con resultados reales
  datos_combinados <- surveys |>
    inner_join(election_data_grouped, 
               by = c("ano_elec" = "anno", "partidos" = "partidos")) |>
    mutate(
      error = prob_votos - actual_share_percent # Error: diferencia entre encuesta y resultado real
    )
  
  # Crear tabla con porcentajes
  tabla_procentajes <- datos_combinados |>
    select(
      ano_elec, partidos, prob_votos, actual_share_percent, error
    )
  
  # Análisis del error: promedio y desviación estándar por partido
  errores <- datos_combinados |>
    group_by(partidos) |>
    summarise(
      mean_error = mean(error, na.rm = TRUE), # Error promedio
      sd_error = sd(error, na.rm = TRUE), # Desviación estándar del error
      n = n(), # Número de observaciones
      .groups = "drop"
    )
  
  list(
    tabla_procentajes = tabla_procentajes, # Tabla con porcentajes
    errores = errores # Estadísticas del error
  )
}

# Aplicar la función a los conjuntos de datos para todos los años
resultados <- calibrar_error(election_data_tidy_select, surveys_tidy_select)

# Resultados
tabla_procentajes <- resultados$tabla_procentajes # Tabla con porcentajes estimados y reales
errores <- resultados$errores # Estadísticas del error

# Mostrar las tablas
print(tabla_procentajes) # Vista previa de la tabla con porcentajes
# A tibble: 567 × 5
   ano_elec partidos prob_votos actual_share_percent  error
      <dbl> <chr>         <dbl>                <dbl>  <dbl>
 1     2008 PSOE           43.4                35.1    8.34
 2     2008 PNV             6                  27.6  -21.6 
 3     2008 ERC             4                   7.23  -3.23
 4     2008 PP             38.1                41.8   -3.70
 5     2008 PSOE           43                  35.1    7.94
 6     2008 PNV             6                  27.6  -21.6 
 7     2008 ERC             5                   7.23  -2.23
 8     2008 PP             39                  41.8   -2.80
 9     2008 PSOE           42.6                35.1    7.54
10     2008 PNV             6                  27.6  -21.6 
# ℹ 557 more rows
Code
print(errores) # Estadísticas del error
# A tibble: 5 × 4
  partidos mean_error sd_error     n
  <chr>         <dbl>    <dbl> <int>
1 BNG          -11.0     0.641    15
2 ERC           -4.81    1.23    103
3 PNV          -25.8     1.15    109
4 PP            -3.37    1.46    170
5 PSOE           7.21    1.69    170

Pregunta 4: ¿Cómo analizar la relación entre censo y voto? ¿Es cierto que determinados partidos ganan en las zonas rurales?

Siguiendo la clasificación establecida por el Ministerio de Agricultura y Pesca de España, se definen las zonas de la siguiente manera:

  • Rural: Aglomeraciones con menos de 2.000 habitantes.
  • Semi-rural: Aglomeraciones con hasta 10.000 habitantes.
  • Urbano: Aglomeraciones con más de 10.000 habitantes.

Pregunta 4: ¿Cómo analizar la relación entre censo y voto? ¿Es cierto que determinados partidos ganan en las zonas rurales?

Con base en esta clasificación, hemos creado la variable “tipo_zona” como paso previo al análisis.

Code
distribucion_voto <- election_filtered |> 
  mutate(tipo_zona = case_when(
    censo < 2000 ~ "Rural",
    censo >= 2000 & censo <= 10000 ~ "Semiurbano",
    censo > 10000 ~ "Urbano"
  )) |> 
  mutate(partidos = as_factor(partidos),
         tipo_zona = factor(tipo_zona,
                         levels = c("Rural", "Semiurbano", "Urbano"),
                         ordered = TRUE))

# Agrupación por tipo de zona y partidos

porc_distribucion_voto <- distribucion_voto |> 
  group_by(tipo_zona) |> 
  mutate(total_votos_zona = sum(votos, na.rm = TRUE)) |> 
  group_by(tipo_zona, partidos) |> 
  summarise(
    total_votos_partido = sum(votos, na.rm = TRUE),
    porcentaje_votos = (total_votos_partido / total_votos_zona[1]) * 100, 
    .groups = "drop"
  )

# Ver el resultado
porc_distribucion_voto
Code
ggplot(porc_distribucion_voto, aes(x = tipo_zona, y = porcentaje_votos, fill = partidos)) +
  geom_bar(stat = "identity", position = "fill") +
  geom_text(
    aes(
      label = paste0(round(porcentaje_votos, 1), "%")
    ),
    position = position_fill(vjust = 0.5), # Centra las etiquetas en las barras
    size = 3, 
    color = "white"
  ) +
  scale_fill_manual(
    values = c(
     "VOX" = "#80b042",      
      "PP" = "#004a95",
      "PSOE" = "#e30613",
      "UP" = "#a668f3",
      "CS" = "#ff956a",
      "PNV" = "#917b66",
      "ERC" = "#edc158",
      "OTROS" = "gray" 
    )
  ) +
  labs(
    title = "Distribución de votos por tipo de zona",
    x = "Tipo de zona",
    y = "Porcentaje de votos (%)",
    fill = "Partidos"
  ) +
  scale_y_continuous(labels = scales::percent_format(scale = 100)) +
  theme_minimal()

Pregunta 4: ¿Cómo analizar la relación entre censo y voto? ¿Es cierto que determinados partidos ganan en las zonas rurales?

Si los votos (votos) son valores numéricos y deseas analizar si las medias de votos difieren significativamente entre tipos de zona para cada partido, puedes usar ANOVA.

Code
# Crear tabla de contingencia
tabla_contingencia <- distribucion_voto |>
  group_by(tipo_zona, partidos) |>
  summarise(
    total_votos = sum(votos, na.rm = TRUE),
    .groups = "drop"
  ) |>
  pivot_wider(
    names_from = partidos,
    values_from = total_votos,
    values_fill = 0
  )

# Convertir a matriz para el test de Chi-cuadrado
matriz_contingencia <- as.matrix(tabla_contingencia[, -1]) # Eliminar la columna 'tipo_zona'

# Realizar el test de Chi-cuadrado
test_chi2 <- chisq.test(matriz_contingencia)

# Resultados del test
print(test_chi2)

    Pearson's Chi-squared test

data:  matriz_contingencia
X-squared = 1817609, df = 16, p-value < 2.2e-16
Code
# Evaluar residuales estandarizados (para ver dónde están las mayores diferencias)
residuales_estandarizados <- test_chi2$stdres
print(residuales_estandarizados)
          PSOE         PP       PNV        CS       ERC       BNG        UP
[1,]  459.0905  296.12411 -58.04050 -545.0381  204.5296 -150.3846 -578.8896
[2,]  455.4392  -39.68112 157.53899 -441.0966  184.7465  387.1418 -405.6246
[3,] -690.5662 -157.70441 -98.31582  733.9006 -291.9876 -236.5788  725.2347
     EH - BILDU       VOX
[1,]   178.2018 -145.2666
[2,]   226.5804 -104.1849
[3,]  -311.0199  184.0592

El análisis confirma que existe una relación estadísticamente significativa entre el tipo de zona y el voto a un partido político. Esto sugiere que ciertos partidos tienen más apoyo en zonas rurales, semiurbanas o urbanas, y que este patrón es consistente.

Pregunta 4: ¿Cómo analizar la relación entre censo y voto? ¿Es cierto que determinados partidos ganan en las zonas rurales?

NO ME FUNCIONA ME QUEDO POR AQUI PREGUNTAR A CHAT GPT POR Análisis de correlación entre el censo poblacional y el porcentaje de votos por partido

Pregunta 4: ¿Cómo analizar la relación entre censo y voto? ¿Es cierto que determinados partidos ganan en las zonas rurales?

# Reordenando los partidos 
datos_distribucion_voto <- 
  distribucion_voto |> 
  mutate("median_votos" = median(votos), .by = c(tipo_zona,partidos)) |>
  mutate("partidos" = fct_reorder(partidos, median_votos))

# Remover outliers usando a regra do IQR
q1 <- quantile(datos_distribucion_voto$votos, 0.25)
q3 <- quantile(datos_distribucion_voto$votos, 0.75)
iqr <- q3 - q1

# Filtrando os dados para remover outliers
datos_election_clean <- datos_distribucion_voto |>
  filter(votos >= (q1 - 1.5 * iqr) & votos <= (q3 + 1.5 * iqr))

Pregunta 4: ¿Cómo analizar la relación entre censo y voto? ¿Es cierto que determinados partidos ganan en las zonas rurales?

Code
# boxplot
ggplot(datos_election_clean) +
  geom_boxplot(aes(x = partidos, y = votos, fill = median_votos ),
               alpha = 0.5) +
  scale_fill_gradient2(low = "red", mid = "white", high = "green",
                       midpoint = 2000) +
  facet_wrap(~tipo_zona,scales = "free_y") +
  theme_minimal() +
  theme(axis.text.x = element_text(angle = 90))

Pregunta 5: ¿Cúal es la evolución en la participación (participación_1 y participación_2) en los municipios con más de 50.000 habitantes, y cómo varía según el partido más votado?

  • El Partido Popular (PP) y el Partido Socialista Obrero Español (PSOE) dominan en participación acumulada, con líneas más destacadas y continuas en todos los periodos.

  • Otros partidos como ERC, PNV y UP muestran una participación más estable y con menos variabilidad.

  • Vox y Ciudadanos (CS) tienen líneas menos pronunciadas, indicando que su impacto es menor en municipios grandes.

  • El año más reciente (probablemente 2019) muestra un aumento drástico en participación para los municipios donde ganó el PSOE.

  • Esto sugiere que, aunque el PP mantiene una base de participación estable, el PSOE ha conseguido movilizar a más votantes recientemente.

Pregunta 5: ¿Cúal es la evolución en la participación (participación_1 y participación_2) en los municipios con más de 50.000 habitantes, y cómo varía según el partido más votado?

Code
# Filtrar municipios con más de 50.000 habitantes
municipios_grandes <- datos_election |> 
  filter(censo > 50000) 

# Calcular la suma de participación y votos por municipio y año
participacion_municipios <- municipios_grandes |> 
  group_by(anno, cod_mun, municipio) |> 
  summarise(
    participacion_1 = sum(participacion_1),
    participacion_2 = sum(participacion_2),
    votos_totales = sum(votos),
    partido_ganador = partidos[which.max(votos)]
  ) |> 
  ungroup()

Pregunta 5: ¿Cúal es la evolución en la participación (participación_1 y participación_2) en los municipios con más de 50.000 habitantes, y cómo varía según el partido más votado?

Code
# Visualizar la evolución de la participación por partido
ggplot(participacion_municipios, aes(x = anno, y = participacion_1, color = partido_ganador)) +
  geom_line() +
  geom_point() +
  labs(
    title = "Evolución de la Participación en Municipios con Más de 50.000 Habitantes",
    x = "Año",
    y = "Participación (Primera Vuelta)",
    color = "Partido Ganador"
  ) +
  theme_minimal()

Pregunta 6: ¿Cuál fue el partido más votado en cada municipio durante el año más reciente disponible en el dataset?

Code
# Filtrar el año más reciente
anio_reciente <- max(datos_election$anno)

# Filtrar datos del año más reciente
datos_recientes <- datos_election |> 
  filter(anno == anio_reciente)

# Determinar el partido más votado por municipio
partido_ganador_municipio <- datos_recientes |> 
  group_by(municipio) |> 
  summarise(partido_ganador = partidos[which.max(votos)]) |> 
  ungroup()

# Mostrar resultados
print(partido_ganador_municipio)
# A tibble: 8,114 × 2
   municipio                         partido_ganador
   <chr>                             <chr>          
 1 Ababuj                            PP             
 2 Abades                            PP             
 3 Abadiño                           PNV            
 4 Abadía                            PSOE           
 5 Abadín                            PP             
 6 Abajas                            PSOE           
 7 Abaltzisketa                      PNV            
 8 Abanilla                          PP             
 9 Abanto                            PP             
10 Abanto y Ciérvana-Abanto Zierbena PNV            
# ℹ 8,104 more rows